import apple.laf.JRSUIConstants.ShowArrows

/**
 * author:vesper.z
 * date: 2024  17:51
 * class: Test08
 * description：Kotlin 扩展
 **/
class Test08 {

}

/**
 * 扩展函数
 * 拓展函数可以已有类中添加新的方法，不会对原类进行修改
 */
class TestExport

fun TestExport.show() {//拓展函数
    println("export")
}

//为Array<Int>拓展一个排序的函数
fun Array<Int>.paixu(): Array<Int> {
    val n = this.size
    for (i in 0 until n - 1) {//until 不要区间最后一个值
        for (j in 0 until n - i - 1) {
            if (this[j] > this[j + 1]) {
                // 交换 arr[j] 和 arr[j+1]
                val temp = this[j]
                this[j] = this[j + 1]
                this[j + 1] = temp
            }
        }
    }
    return this
}

/**
 * 拓展函数是静态解析的
 * 拓展函数是静态解析的，并不是接受者类型的虚拟成员，在调用拓展函数时，
 * 具体被调用过的是哪个函数，由调用函数的对象表达式来决定，而不是动态的类型决定。
 */
open class AAA

class BBB : AAA() {
    fun show() {//同名的对象函数和拓展函数，对象函数的优先级高于拓展函数。
        println("对象函数")
    }
}

fun AAA.show() = "拓展函数 aaa"
fun BBB.show() = "拓展函数 bbb"
fun showA(aaa: AAA) {
    println(aaa.show()) //具体被调用过的是哪个函数，由调用函数的对象表达式来决定
}

fun showB(bbb: BBB) {
    println(bbb.show()) //具体被调用过的是哪个函数，由调用函数的对象表达式来决定
}

/**
 * 拓展一个空对象
 * 在拓展函数内可用通过this判断被接受者是否为null，这样即使接受者为null也可以使用拓展函数
 */
fun Any.toString(): String {
    if (this == null) return "null"
//    空检测之后，this会自动转换为非空类型，所以下面的 toString()解析为Any 类的成员函数
    return toString()
}
//拓展一个属性
//获取最后一个字符
val String.lastChar:Char
    get() {
        var array = this.toCharArray()
        return array[this.length-1]
    }

/**
 * 伴生对象的拓展
 */
//如果一个类定义有一个伴生对象，可以为伴生对象定义拓展函数和属性
//伴生对象通过"类名."形式调用伴生对象，伴生对象声明的拓展函数，通过用类名限定符来调用：
class MyClass{
    companion object {//被称为Companion

    }
}
fun MyClass.Companion.foo(){
    println("伴生方法")
}
val MyClass.Companion.arg:String
    get() {
        return "伴生属性"
    }


/**
 * 拓展的作用域
 * 通常拓展的函数或属性定义在顶级包下
 * 要使用所定义包之外的一个拓展，通过import导入拓展的函数名进行使用。
 */

/**
 *
 * 拓展声明为成员
 * 在一个类的内部你可以为另一个类声明拓展
 * 在这个拓展中有多个隐含的接受者，其中扩展方法定义所在类的实例称为分发接受者，而扩展方法的目标类型的实例称为扩展接受者。
 */
class D{
    fun f1(){
        println("D的方法")
    }
}
class E{
    fun f2(){
        println("C的方法")
    }
    fun D.foo(){
        println("D 的拓展方法")
        f1()
        f2()
    }
    fun  caller(d:D){
        d.foo()
    }


}


fun main(args: Array<String>) {
//    test7
    var d = D()
    var e = E()
    e.caller(d)

//    test6
    println(MyClass.arg)


    //test5
    var str:String = "123456789"
    println(str.lastChar)

    //test4
    var any: Any? = null
    println(any.toString())

    //test3
    showA(AAA())
    showA(BBB())
    showB(BBB())

    //test2
    var arrayList: Array<Int> = arrayOf(48, 56, 5)
    arrayList.paixu()
    val n = arrayList.paixu().size
    for (i in 0 until n) {
        println("" + arrayList[i])
    }


    //test1
    TestExport().show()
}